package com.tang.portal.facade.admin.sys;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.tang.framework.core.domain.HttpResult;
import com.tang.framework.core.model.LoginUser;
import com.tang.common.model.req.ReqId;
import com.tang.common.constant.Constant;
import com.tang.common.model.req.ReqIds;
import com.tang.common.model.res.ResSysDictValueTableItem;
import com.tang.service.admin.domain.SysDictType;
import com.tang.service.admin.domain.SysDictValue;
import com.tang.service.admin.model.req.ReqSysDictValue;
import com.tang.service.admin.model.req.ReqSysDictValueAdd;
import com.tang.service.admin.model.res.ResSysDictValueDetail;
import com.tang.service.admin.service.ISysDictTypeService;
import com.tang.service.admin.service.ISysDictValueService;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.BeanUtils;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

import static com.tang.common.utils.excel.ExcelUtils.getStyleStrategy;

/**
 * @author tang jun liang
 * @Date ${gen.dateTime}
 */
@Service
public class SysDictValueFacade {

    @Resource
    private ISysDictValueService sysDictValueService;

    @Resource
    private ISysDictTypeService sysDictTypeService;

    @Resource
    private ApplicationEventPublisher publisher;

    @Resource
    private RedissonClient redissonClient;


    /**
     * 字典值删除
     *
     * @param ids
     * @param currLoginUser
     * @return
     */
    public HttpResult<String> remove(ReqIds ids, LoginUser currLoginUser) {
        sysDictValueService.removeBatchByIds(ids.getIds());
        publisher.publishEvent(new ResSysDictValueTableItem());
        return HttpResult.ok();
    }

    /**
     * 字典值详情
     *
     * @param id
     * @param currLoginUser
     * @return
     */
    public HttpResult<ResSysDictValueDetail> detail(ReqId id, LoginUser currLoginUser) {
        SysDictValue sysDictValue = sysDictValueService.getById(id.getId());
        ResSysDictValueDetail resSysDictValueDetail = new ResSysDictValueDetail();
        BeanUtils.copyProperties(sysDictValue, resSysDictValueDetail);
        return HttpResult.ok(resSysDictValueDetail);
    }

    /**
     * 字典值列表
     *
     * @param reqSysDictValue
     * @param currLoginUser
     * @return
     */
    public HttpResult<IPage<ResSysDictValueTableItem>> list(ReqSysDictValue reqSysDictValue, LoginUser currLoginUser) {
        if (Objects.nonNull(reqSysDictValue.getDictTypeName())) {
            RList<ResSysDictValueTableItem> list = redissonClient.getList(reqSysDictValue.getDictTypeName());
            if (list.isEmpty()) {
                publisher.publishEvent(new ResSysDictValueTableItem());
            } else {
                Page<ResSysDictValueTableItem> page = new Page<>();
                page.setRecords(list);
                return HttpResult.ok(page);
            }
        }
        IPage<ResSysDictValueTableItem> page = sysDictValueService.selectJoinListPage(
                new Page<>(reqSysDictValue.getPageNum(), reqSysDictValue.getPageSize()),
                ResSysDictValueTableItem.class,
                new MPJLambdaWrapper<SysDictValue>()
                        .selectAll(SysDictValue.class)
                        .selectAs(SysDictType::getName, ResSysDictValueTableItem::getDictTypeName)
                        .leftJoin(SysDictType.class, SysDictType::getId, SysDictValue::getDictTypeId)
                        .eq(Objects.nonNull(reqSysDictValue.getDictTypeId()), SysDictValue::getDictTypeId, reqSysDictValue.getDictTypeId())
                        .leftJoin(SysDictType.class, SysDictType::getId, SysDictValue::getDictTypeId)
                        .eq(StringUtils.isNotBlank(reqSysDictValue.getDictTypeName()), SysDictType::getName, reqSysDictValue.getDictTypeName())
        );

        return HttpResult.ok(page);
    }

    /**
     * 新增字典值
     *
     * @param sysDictValueAdd
     * @return
     */
    public HttpResult<String> add(ReqSysDictValueAdd sysDictValueAdd) {
        SysDictValue sysDictValue = new SysDictValue();
        BeanUtils.copyProperties(sysDictValueAdd, sysDictValue);
        sysDictValue.setLabel(sysDictValue.getLabel().toUpperCase());
        sysDictValueService.saveOrUpdate(sysDictValue);
        publisher.publishEvent(new ResSysDictValueTableItem());
        return HttpResult.ok();
    }

    /**
     * 更新字典值
     *
     * @param sysDictValueAdd
     * @return
     */
    public HttpResult<String> update(ReqSysDictValueAdd sysDictValueAdd) {
        return add(sysDictValueAdd);
    }


    /**
     * 导出字典值表
     *
     * @param ids
     * @param httpServletResponse
     */
    @SneakyThrows
    public void export(ReqIds ids, HttpServletResponse httpServletResponse) {
        String fileName = URLEncoder.encode("字典值.xlsx", StandardCharsets.UTF_8);
        // 设置响应体
        httpServletResponse.setContentType("application/vnd.ms-excel");
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setHeader("Content-disposition", "attachment;filename=" + fileName);
        List<SysDictValue> sysDictValueList = sysDictValueService
                .lambdaQuery()
                .in(!ids.getIds().isEmpty(), SysDictValue::getId, ids.getIds())
                .eq(Objects.nonNull(ids.getId()), SysDictValue::getDictTypeId, ids.getId())
                .list();
        EasyExcel.write(httpServletResponse.getOutputStream(), SysDictValue.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(getStyleStrategy())
                .sheet("字典值").doWrite(sysDictValueList);
    }


    /**
     * 导入excel
     *
     * @param file
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult<String> importExcel(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        EasyExcel.read(inputStream, ReqSysDictValueAdd.class, new AnalysisEventListener<ReqSysDictValueAdd>() {
            final List<SysDictValue> sysDictValueList = new ArrayList<>();

            @Override
            public void invoke(ReqSysDictValueAdd sysDictValueAdd, AnalysisContext analysisContext) {
                SysDictValue sysDictValue = new SysDictValue();
                BeanUtils.copyProperties(sysDictValueAdd, sysDictValue);
                sysDictValueList.add(sysDictValue);
                if (sysDictValueList.size() == Constant.MAX_BATCH) {
                    sysDictValueService.saveBatch(sysDictValueList);
                    sysDictValueList.clear();
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                sysDictValueService.saveBatch(sysDictValueList);
            }
        });
        return HttpResult.ok();
    }

    /**
     * 导出模版
     *
     * @param httpServletResponse
     */
    @SneakyThrows
    public void exportTemplate(HttpServletResponse httpServletResponse) {
        String fileName = URLEncoder.encode("字典值导入模版.xlsx", StandardCharsets.UTF_8);
        // 设置响应体
        httpServletResponse.setContentType("application/vnd.ms-excel");
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setHeader("Content-disposition", "attachment;filename=" + fileName);
        EasyExcel.write(httpServletResponse.getOutputStream(), SysDictValue.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(getStyleStrategy())
                .sheet("字典值").doWrite(List.of());
    }


}
